﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Threading;
using AsyncCallback.AsyncEvent;

namespace AsyncCallback
{
    class Program
    {
        static void Main(string[] args)
        {
            Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
            Trace.AutoFlush = true;
            Trace.Indent();
            MyPointDemon();
            Trace.Unindent();
            Console.Read();
        }

        static void NormalAsyncCallDemo()
        {
            Calculator calculator = new Calculator();
            BinaryOperation oppDel = calculator.Add;
            oppDel += calculator.Subtraction;
            IAsyncResult asyncResult1 = oppDel.BeginInvoke(2, 3, null, null);
            IAsyncResult asyncResult2 = oppDel.BeginInvoke(4, 5, null, null);

            int result;
            result = oppDel.EndInvoke(asyncResult1);
            Debug.Assert(result == 5);

            result = oppDel.EndInvoke(asyncResult2);
            Debug.Assert(result == 9);
        }

        static void CalculatorClientDemo()
        {
            CalculatorClient client = new CalculatorClient();
            client.AsyncAdd(5, 6);
        }

        static void WaitOneDemo()
        {
            Calculator calculator = new Calculator();
            BinaryOperation oppDel = calculator.Add;

            IAsyncResult asyncResult = oppDel.BeginInvoke(2, 3, null, null);
            /*其它代码*/
            asyncResult.AsyncWaitHandle.WaitOne();//这里可能会被阻塞

            int result;
            result = oppDel.EndInvoke(asyncResult);//这里不会被阻塞
            Debug.Assert(result == 5);
        }

        static void WaitOneTimeOutDemon()
        {
            Calculator calculator = new Calculator();
            BinaryOperation oppDel = calculator.Add;

            IAsyncResult asyncResult = oppDel.BeginInvoke(2, 3, null, null);
            while (asyncResult.IsCompleted == false)
            {
                asyncResult.AsyncWaitHandle.WaitOne(10, false);//这里可能会被阻塞
            }
            int result;
            result = oppDel.EndInvoke(asyncResult);//这里不会被阻塞
            Debug.Assert(result == 5);
        }

        static void MultipleAsyncCallDemo()
        {
            Calculator calcutor = new Calculator();
            BinaryOperation oppDel1 = calcutor.Add;
            BinaryOperation oppDel2 = calcutor.Add;

            IAsyncResult asyncResult1 = oppDel1.BeginInvoke(2, 3, null, null);
            IAsyncResult asyncResult2 = oppDel2.BeginInvoke(4, 5, null, null);
            Trace.WriteLine("add before...");
            WaitHandle[] handleArray = new WaitHandle[] { asyncResult1.AsyncWaitHandle, asyncResult2.AsyncWaitHandle };
            WaitHandle.WaitAll(handleArray);

            int result;
            //调用EndInvoke不会阻塞
            result = oppDel1.EndInvoke(asyncResult1);
            Debug.Assert(result == 5);

            result = oppDel2.EndInvoke(asyncResult2);
            Debug.Assert(result == 9);
            Trace.WriteLine("add over...");
        }

        static void AsyncCallBackDemo()
        {
            CalculatorClient calculator_client = new CalculatorClient();
            calculator_client.AsyncAdd(5, 10);
        }

        static void FileAsyncReadDemo()
        {
            FileStreamClient file_stream_client = new FileStreamClient();
            file_stream_client.AsyncRead();
        }

        static void DivideErrorDemon()
        {
            CalculatorClient client = new CalculatorClient();
            client.AsyncDivide(10, 10);
        }

        static void SubscribeEventDemo()
        {
            MyPublisher publisher = new MyPublisher();
            MySubscriber sub_1 = new MySubscriber();
            MySubscriber sub_2 = new MySubscriber();
            MySubscriber sub_3 = new MySubscriber();
            publisher.NumberChanged += sub_1.OnNumberChanged;
            publisher.NumberChanged += sub_2.OnNumberChanged;
            publisher.NumberChanged += sub_3.OnNumberChanged;
            publisher.FireEvent(10);
        }

        static void MyPointDemon()
        {
            MyPointClient client = new MyPointClient();
            client.AysncSwap();
        }
    }
}
